﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.Windows;
using System.Windows.Forms;

namespace SvnMonitor
{
    static class MinimizeToTray
    {
        /// <summary>
        /// Enables "minimize to tray" behavior for the specified Window.
        /// </summary>
        /// <param name="window">Window to enable the behavior for.</param>
        public static MinimizeToTrayInstance Enable(Window window)
        {
            // No need to track this instance; its event handlers will keep it alive
            return new MinimizeToTrayInstance(window);
        }
    }

    /// <summary>
    /// Class implementing "minimize to tray" functionality for a Window instance.
    /// </summary>
    class MinimizeToTrayInstance
    {
        private readonly Window _window;
        private NotifyIcon _notifyIcon;
        private bool _balloonShown;

        public string Text
        {
            get
            {
                if (_notifyIcon == null)
                    return null;

                return _notifyIcon.Text;
            }
            set
            {
                if (_notifyIcon != null)
                    _notifyIcon.Text = value;
            }
        }

        public Icon Icon
        {
            get
            {
                return _notifyIcon.Icon;
            }
            set
            {
                _notifyIcon.Icon = value;
            }
        }

        /// <summary>
        /// Initializes a new instance of the MinimizeToTrayInstance class.
        /// </summary>
        /// <param name="window">Window instance to attach to.</param>
        public MinimizeToTrayInstance(Window window)
        {
            Debug.Assert(window != null, "window parameter is null.");
            _window = window;
            _window.StateChanged += HandleStateChanged;
        }

        public void HideBallon()
        {
            // TODO:
        }

        /// <summary>
        /// Handles the Window's StateChanged event.
        /// </summary>
        /// <param name="sender">Event source.</param>
        /// <param name="e">Event arguments.</param>
        private void HandleStateChanged(object sender, EventArgs e)
        {
            if (_notifyIcon == null)
            {
                // Initialize NotifyIcon instance "on demand"
                _notifyIcon = new NotifyIcon();
                _notifyIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetEntryAssembly().Location);
                _notifyIcon.MouseClick += HandleNotifyIconOrBalloonClicked;
                _notifyIcon.BalloonTipClicked += HandleNotifyIconOrBalloonClicked;
            }
            // Update copy of Window Title in case it has changed
            _notifyIcon.Text = _window.Title;

            // Show/hide Window and NotifyIcon
            var minimized = (_window.WindowState == WindowState.Minimized);
            _window.ShowInTaskbar = !minimized;
            _notifyIcon.Visible = minimized;
            if (minimized && !_balloonShown)
            {
                // If this is the first time minimizing to the tray, show the user what happened
                _notifyIcon.ShowBalloonTip(300, null, _window.Title, ToolTipIcon.None);
                _balloonShown = true;
            }
        }

        /// <summary>
        /// Handles a click on the notify icon or its balloon.
        /// </summary>
        /// <param name="sender">Event source.</param>
        /// <param name="e">Event arguments.</param>
        private void HandleNotifyIconOrBalloonClicked(object sender, EventArgs e)
        {
            // Restore the Window
            _window.WindowState = WindowState.Normal;
        }
    }

}
